#include <cv.h>
#include <highgui.h>
#include "abstractProbabilityTransformer.hpp"
#include "abstractFilter.hpp"
#include "resourceTracker.h"
#include "faceDetector.h"
#include "handTracker.hpp"
#include "HIVideoCapture.hpp"
#include "handLocaliser.hpp"
//FIXNOW determine reason for segfault

#include <iostream>
//TODO clean up includes

//this looks up the location of the gtest files in header hiDependenciesForTestFramework.h
//TODO : Design choice? currently I'll keep this dependency in a very specific header file
// as changing it should cause minimal recompilation.

#include "hiDependenciesForTestFramework.h"
#include "gtest.h"

//NOTE: hiDependenciesForTestFramework sets HI_TEST_VISUALISATION
//which if set will make tests compile to show images of the things they test.

using namespace cv;

namespace {
	
	// The fixture for testing class PerPixelProbabilityTransformerTest.
	class HandTrackerTest : public ::testing::Test {
	public:
		
		HandTracker *ht;
//		ResourceTracker *rt;
		
	protected:
		
		virtual void SetUp() {
//			rt = new ResourceTracker( "../config/runtimeSettings/cfg.xml" );
//			rt->loadCategory("TestData");
			
			
			//ASSERT_TRUE( cap->isOpened() );
		}
		
		virtual void TearDown() {
//			delete rt;
			//delete ht;
			//delete cap;
		}
		
	};
	
}

//TEST_F(HandTrackerTest, tracksVideo) {
//	
//	Mat frame;
//	(*cap) >> frame;
//	flip( frame, frame, 1);
//	
//	Rect trackingRect = Rect( 0, 0, 100, 100 );
//	
//	ht = HandTracker::init( trackingRect, frame );
//	
//	namedWindow( "tracking test", 1 );
//	
//	while ( waitKey(1) != 27) { //not escape
//		trackingRect = ht->track( frame );
//		
//		rectangle( frame, Point(trackingRect.x, trackingRect.y),
//				  Point(trackingRect.x + trackingRect.width, trackingRect.y + trackingRect.height),
//				  Scalar::all(250));
//		
//		imshow( "tracking test", frame );
//		
//		(*cap) >> frame;
//		
//		flip( frame, frame, 1);
//	}
//	
//}

//TEST_F(HandTrackerTest, tracksVideoWithLocaliser) {
//	HIVideoCapture *cap;
//	cap = new HIVideoCapture(0);
//	
//	Mat frame;
//	(*cap) >> frame;
//	flip( frame, frame, 1);
//	
//	HandLocaliser* hl = new HandLocaliser();
//	
//	Rect trackingRect = hl->localiseHand( frame );
//	
//	//forcing rectangle to stay inside frame
//	//FIX: this approach is simplistic?
//	//used clipped frame instead?
//	//maybe not, this approach does seem quite easy to use as user
//	if ( trackingRect.x < 0 ) trackingRect.x = 0;
//	if ( frame.cols < trackingRect.x + trackingRect.width ) trackingRect.x = frame.cols - trackingRect.width;
//	if ( trackingRect.y < 0 ) trackingRect.y = 0;
//	if ( frame.rows < trackingRect.y + trackingRect.height ) trackingRect.y = frame.rows - trackingRect.height;
//	
//	ht = HandTracker::init( hl->getProbabilityTransformer(), trackingRect, frame, Ptr< AbstractFilter >(new OpenFilter(4))  );
//	
//	namedWindow( "tracking test 1", 1 );
//	namedWindow( "tracking test 2", 1 );
//	
//	
//	while ( waitKey(1) != 27) { //not escape
//		trackingRect = ht->track( frame );
//		
////		rectangle( frame, Point(trackingRect.x, trackingRect.y),
////				  Point(trackingRect.x + trackingRect.width, trackingRect.y + trackingRect.height),
////				  Scalar::all(250));
//		
//		//imshow( "tracking test", frame );
//		
//		(*cap) >> frame;
//		
//		flip( frame, frame, 1);
//		
//		
//	}
//	
//	delete cap;
//	
//}

//TEST_F(HandTrackerTest, testLocaliser) {
//	
//	HandLocaliser* hl = new HandLocaliser();
//
//	ResourceTracker* rt = new ResourceTracker( "../config/runtimeSettings/cfg.xml" );
//	rt->loadCategory("TestData");
//	
//	Mat frame = rt->getMat("handL_back_tom");
//	
//	Rect trackingRect = hl->localiseHand( frame );
//	
//	AbstractProbabilityTransformer* pt = hl->getProbabilityTransformer();
//	
//	Mat backproj = Mat::zeros(frame.cols, frame.rows, CV_8UC1);
//	
//	Mat hsvFullSize;
//	
//	cvtColor(frame, frame, CV_BGR2HSV);
//	
//	pt->getBackProjection( frame, backproj );
//	
//	if ( trackingRect.x < 0 ) trackingRect.x = 0;
//	if ( frame.cols < trackingRect.x + trackingRect.width ) trackingRect.x = frame.cols - trackingRect.width;
//	if ( trackingRect.y < 0 ) trackingRect.y = 0;
//	if ( frame.rows < trackingRect.y + trackingRect.height ) trackingRect.y = frame.rows - trackingRect.height;
//	
//	namedWindow( "tracking test", 1 );
//	
//	rectangle( backproj, Point(trackingRect.x, trackingRect.y),
//			  Point(trackingRect.x + trackingRect.width, trackingRect.y + trackingRect.height),
//			  Scalar::all(250));
//	
//	imshow( "tracking test", backproj );
//	
//	waitKey(0);
//
//}


TEST_F(HandTrackerTest, tracksRecordingWithLocaliser) {
	
	VideoCapture cap = VideoCapture("locVid1c.avi");
	
	Mat frame;
	cap >> frame;
	flip( frame, frame, 1);
	
	HandLocaliser* hl = new HandLocaliser();
	
	Rect trackingRect = hl->localiseHand( frame );
	
	//forcing rectangle to stay inside frame
	//FIX: this approach is simplistic?
	//used clipped frame instead?
	//maybe not, this approach does seem quite easy to use as user
	if ( trackingRect.x < 0 ) trackingRect.x = 0;
	if ( frame.cols < trackingRect.x + trackingRect.width ) trackingRect.x = frame.cols - trackingRect.width;
	if ( trackingRect.y < 0 ) trackingRect.y = 0;
	if ( frame.rows < trackingRect.y + trackingRect.height ) trackingRect.y = frame.rows - trackingRect.height;
	
	ht = HandTracker::init( hl->getProbabilityTransformer(), trackingRect, frame, Ptr< AbstractFilter >(new OpenFilter(4))  );
	
	namedWindow( "tracking test 1", 1 );
	
	for( int frames = 0; frames<249; frames++){
		trackingRect = ht->track( frame );
		
		//		rectangle( frame, Point(trackingRect.x, trackingRect.y),
		//				  Point(trackingRect.x + trackingRect.width, trackingRect.y + trackingRect.height),
		//				  Scalar::all(250));
		
		//imshow( "tracking test", frame );
		
		cap >> frame;
		
		flip( frame, frame, 1);
		
		waitKey(1);
	}
	
	
//	while ( waitKey(1) != 27) { //not escape
//		trackingRect = ht->track( frame );
//		
//		//		rectangle( frame, Point(trackingRect.x, trackingRect.y),
//		//				  Point(trackingRect.x + trackingRect.width, trackingRect.y + trackingRect.height),
//		//				  Scalar::all(250));
//		
//		//imshow( "tracking test", frame );
//		
//		cap >> frame;
//		
//		flip( frame, frame, 1);
//		
//		
//	}
	
	std::cerr << "hand tracker test 1" << std::endl;
	
}
			
			
		
		
		
